//********************************************************************************************************
// Product Name: MapWindow.dll Alpha
// Description:  The basic module for MapWindow version 6.0
//********************************************************************************************************
// The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License"); 
// you may not use this file except in compliance with the License. You may obtain a copy of the License at 
// http://www.mozilla.org/MPL/ 
//
// Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF 
// ANY KIND, either expressed or implied. See the License for the specificlanguage governing rights and 
// limitations under the License. 
//
// The Original Code is from MapWindow.dll version 6.0
//
// The Initial Developer of this Original Code is Ted Dunsford. Created 3/8/2008 7:19:53 AM
// 
// Contributor(s): (Open source contributors should list themselves and their modifications here). 
//
//********************************************************************************************************

using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;

using MapWindow;
using MapWindow.Main;
using MapWindow.Data;
using MapWindow.Drawing;
using MapWindow.Geometries;


using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;


namespace MapWindow.DirectX
{


    /// <summary>
    /// Texture
    /// </summary>
    public class TileLayerDX: LayerDX, ITileLayerDX
    {

       

        #region Private Variables



        
        private string _directory;
   
        List<TileDX> _tiles;

        


        #endregion

        #region Constructors

        /// <summary>
        /// Creates a new instance of Texture
        /// </summary>
        public TileLayerDX():this(null, null)
        {
           
        }

        /// <summary>
        /// Creates a texture with the specified file.  A Load method will open the existing texture.  A Save method will overwrite it.
        /// </summary>
        /// <param name="directory">The filename to associate with this texture.</param>
        public TileLayerDX(string directory):this(directory, null)
        {
            

        }

        /// <summary>
        /// Creates a texture with the specified file.  A Load method will open the existing texture.  A Save method will overwrite it.
        /// </summary>
        /// <param name="directory">The filename to associate with this texture.</param>
        /// <param name="progressHandler">An IProgressHandler for receiving status messages</param>
        public TileLayerDX(string directory, IProgressHandler progressHandler)
        {

            Configure(directory, progressHandler);
        }

        /// <summary>
        /// Creates a texture with the specified file.  A Load method will open the existing texture.  A Save method will overwrite it.
        /// </summary>
        /// <param name="directory">The filename to associate with this texture.</param>
        /// <param name="container">A container to add this new layer to</param>
        /// <param name="progressHandler">An IProgressHandler for receiving status messages</param>
        public TileLayerDX(string directory, ICollection<ILayer> container, IProgressHandler progressHandler)
            : base(container)
        {
            Configure(directory, progressHandler);
        }



        private void Configure(string directory, IProgressHandler progressHandler)
        {
           
            _directory = directory;
            LegendText = _directory;
            IsVisible = true;
            ProgressHandler = progressHandler;
            
       
            //InitializeBackgoundWorker();

        }

      

     
        #endregion

        #region Methods



        /// <summary>
        /// This is the internal drawing method that follows the standard checks.  Drawing is evoked
        /// through the Draw3D command, but internally implemented in the DrawPart method.  After
        /// the initial checks, the Draw3D method will cycle the part integer from 0 to NumParts -1.
        /// </summary>
        /// <param name="args">A DrawArgsDX class with the device and camera.</param>
        protected override void OnDraw(DrawArgsDX args)
        {
            

            IEnvelope env = new Envelope();
            double x = (double)args.Camera.TargetLocation.X;
            double y = (double)args.Camera.TargetLocation.Y;
            double z = (double)args.Camera.View.Length();

            env.SetExtents(x - z/2, y - z/2, x + z/2, y + z/2);

            // Purge any tiles greater than level 0 that are not currently in view.
            int i = 0;
            foreach (TileDX tile in _tiles)
            {
                if (tile.IsLoaded) // a tile that isn't loaded yet has an invalid extent range
                {
                    if (tile.Envelope.Intersects(env) == false)
                    {
                        tile.Close();
                    }
                }
                i++;
            }



            foreach (TileDX tile in _tiles)
            {
                tile.Draw3D(args);
            }
          

        }

  

        
       

        /// <summary>
        /// Clears directX memory during dispose
        /// </summary>
        /// <param name="disposing">boolean disposing</param>
        protected override void Dispose(bool disposing)
        {
            if (_tiles != null)
            {
                foreach (TileDX tile in _tiles)
                {
                    if (tile != null) tile.Dispose();
                }
            }
            base.Dispose(disposing);
        }

       
        /// <summary>
        /// Opens the texture layer, but doesn't automatically draw it.  Rather it simply creates the texture so that it can be used
        /// by another framework.
        /// </summary>
        /// <param name="device">The Microsoft.DirectX.Direct3D.Device to draw to</param>
        /// <param name="camera">The camera</param>
        public virtual void Open(Device device, Camera camera)
        {
            Open(device, camera, ProgressHandler);
        }

        /// <summary>
        /// This causes this textureLayer to open a data file and load the texture, but does not render the texture.
        /// This should be called before draping this texture on a different frame.
        /// </summary>
        /// <param name="device">A Microsoft.DirectX.Direct3D.Device</param>
        /// <param name="camera"></param>
        /// <param name="progressHandler">progress handler</param>
        public virtual void Open(Device device, Camera camera, IProgressHandler progressHandler)
        {
            ProgressHandler = progressHandler;
         
         
            Initialize(new DrawArgsDX(device, camera));
        }

 

        /// <summary>
        /// This is necessary if the frame is supposed to move.  It will force it to be regenerated during a draw.
        /// </summary>
        public virtual void ResetMesh()
        {
            foreach (ITextureLayerDX tile in _tiles)
            {
                if (tile != null) tile.ResetMesh();
            }

        }


        /// <summary>
        /// this will force the texture to reload
        /// </summary>
        public virtual void ResetTexture()
        {
            foreach (ITextureLayerDX tile in _tiles)
            {
               
            }
        }

       
        /// <summary>
        /// This layer doesn't actually support changing the image.  Instead, this simply updates the worldfile,
        /// but only if the style is georeferenced.
        /// </summary>
        public virtual void Save()
        {
           // Not Implemented
        }

       
        #endregion

        #region Properties

       
        

        /// <summary>
        /// Obtains an envelope that contains this image
        /// </summary>
        /// <returns>An IEnvelope</returns>
        [Category("Bounds"), Description("Gets an envelope containing this."),
        TypeConverter(typeof(ExpandableObjectConverter))]
        public override IEnvelope Envelope
        {
            get
            {
                Envelope env = new Envelope();
                if (_tiles == null || _tiles.Count == 0)
                {
                    env.SetExtents(-180, -90, 180, 90);
                    return env;
                }
                foreach (TileDX tile in _tiles)
                {
                    env.ExpandToInclude(tile.Envelope);
                }
                return env;
            }
           
        }

       

        /// <summary>
        /// Gets or sets a string filename where this texture is found on the disk.
        /// </summary>
        [Category("General"), Description("Gets or sets the string filename to use for this texture.")]
        public virtual string Directory
        {
            get { return _directory; }
            set 
            { 
                _directory = value;
               
            }
        }

      

       
      
       
        #endregion


        #region Private Functions

        

        /// <summary>
        /// Sets up the texture if it has never been drawn before
        /// </summary>
        public override void Initialize(DrawArgsDX args)
        {

            // Load the 0 level of the directory
            string path = _directory + "\\0\\";
            _tiles = new List<TileDX>();
            
            for(int lat = 0; lat < 5; lat++)
            {
                for(int lon = 0; lon < 10; lon++)
                {


                    TileDX tile = new TileDX(_directory, 0, lat, lon, null);
                    _tiles.Add(tile);
                    tile.TextureLoaded += new EventHandler(tile_TextureLoaded);
          
                }
            }
            IsInitialized = true;
            
           
        }

        // Pass up the event so that the map knows that it needs to be updated.
        void tile_TextureLoaded(object sender, EventArgs e)
        {
            OnVisibleChanged(sender, e);
        }


        #endregion

        #region Protected Methods

       
        #endregion






    }

}
